﻿using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Profiling;

#if ODIN_INSPECTOR
using Sirenix.OdinInspector;
#endif

namespace JH
{
    /// <summary>
    ///  数据排序器
    /// </summary>
    [Serializable]
    public abstract class BasicSort<TPoint> : EachProcessor<TPoint>, ISort<TPoint>
        where TPoint : struct
    {
        /// <summary>
        ///  最小值
        /// </summary>
        [field: SerializeField]
#if ODIN_INSPECTOR
        [field: ReadOnly]
        [field: LabelText("最小值")]
#endif
        public TPoint Min { get; private set; }

        /// <summary>
        /// 最大值
        /// </summary>
        [field: SerializeField]
#if ODIN_INSPECTOR
        [field: ReadOnly]
        [field: LabelText("最大值")]
#endif
        public TPoint Max { get; private set; }

        /// <summary>
        ///  排序后的数据列表
        /// </summary>
        [SerializeField]
#if ODIN_INSPECTOR
        [ReadOnly]
        [LabelText("排序后的数据列表")]
#endif
        private List<TPoint> sortedData = new();

        /// <summary>
        ///  排序器
        /// </summary>
        public abstract IComparer<TPoint> Comparer { get; }

        /// <summary>
        ///  按照Y值排序后的数据列表
        /// </summary>
        public IReadOnlyList<TPoint> SortedData => sortedData;

        /// <summary>
        ///  图表数据
        /// </summary>
        private IChart<TPoint> _data;

        /// <summary>
        ///  当数据点添加时，需要进行的处理
        /// </summary>
        public override void Process()
        {
            // 清空之前的数据
            sortedData.Clear();

            // 遍历数据列表，添加到排序列表中
            for (int i = 0; i < Data.Data.Count; i++)
            {
                var point = Data.Data[i];

                var index = sortedData.BinarySearch(point, Comparer);

                // 如果没有对应的元素，获取插入位置
                if (index < 0) index = ~index;

                // 插入数据点到排序列表中
                sortedData.Insert(index, point);
            }

            // 更新最小值和最大值
            if (sortedData.Count > 0)
            {
                Min = sortedData[0];
                Max = sortedData[^1];
            }
            else
            {
                Min = default;
                Max = default;
            }
        }
    }
}